/**
 * Copyright (c) 2005-2006 JavaGameNetworking
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'JavaGameNetworking' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Created: Jul 29, 2006
 */
package com.captiveimagination.jmenet;

import com.captiveimagination.jgn.synchronization.GraphicalController;
import com.captiveimagination.jgn.synchronization.message.SynchronizeCreateMessage;
import com.captiveimagination.jgn.synchronization.message.SynchronizeMessage;
import com.captiveimagination.jgn.synchronization.message.SynchronizeRemoveMessage;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Spatial;
import com.jme.scene.Spatial.CullHint;

import de.bazinga.rotw.collision.CollidableObjects;
import de.bazinga.rotw.network.message.SynchronizePlayerMessage;
import de.bazinga.rotw.person.Person;
import de.bazinga.rotw.vehicle.Car;
import de.bazinga.rotw.vehicle.Vehicle;

/**
 * This is a basic implementation of the GraphicalControler for the
 * jME project.
 * 
 * @author Matthew D. Hicks
 */
public class JMEGraphicalController implements GraphicalController<Spatial> {
    public void applySynchronizationMessage(SynchronizeMessage message, Spatial spatial) {
    	SynchronizePlayerMessage m = (SynchronizePlayerMessage)message;
        
        
        
        
        // apply animation
        if(!(spatial instanceof Person)) {
        	
        	spatial.getLocalTranslation().x = m.getPositionX();
            spatial.getLocalTranslation().y = m.getPositionY();
            spatial.getLocalTranslation().z = m.getPositionZ();
            
            spatial.getLocalRotation().x = m.getRotationX();
            spatial.getLocalRotation().y = m.getRotationY();
            spatial.getLocalRotation().z = m.getRotationZ();
            spatial.getLocalRotation().w = m.getRotationW();
            
        }else{
        	Person p = (Person)spatial;
        	
        	((Person)spatial).setBulletColor(m.getBulletColor());
        	((Person)spatial).setPlayerName(m.getPlayerName());
        	((Person)spatial).setScore(m.getScore());
        	
        	((Person)spatial).setTeam(m.getTeam());
        	
        	
        	// Set Vehicle
        	if(m.getVehicleIndex() >= 0) {
        		Vehicle veh = (Vehicle)CollidableObjects.getInstance().getObjects("vehicle").get(m.getVehicleIndex());
    			

        		
        		if(veh instanceof Car) {
        			Quaternion rot = new Quaternion();
        			rot.setX(m.getRotationX());
        			rot.setY(m.getRotationY());
        			rot.setZ(m.getRotationZ());
        			rot.setW(m.getRotationW());
        			((Car)veh).getPhysicsCar().setLocalRotation(rot);
        			//((Car)veh).getPhysicsCar().getLocalRotation().y = m.getRotationY();
        			//((Car)veh).getPhysicsCar().getLocalRotation().z = m.getRotationZ();
        			//((Car)veh).getPhysicsCar().getLocalRotation().w = m.getRotationW();
                    
        			Vector3f vehicleLoc = new Vector3f(
	        				m.getPositionX(),
	        				m.getPositionY(),
	        				m.getPositionZ());
	        		((Car)veh).getPhysicsCar().setLocalTranslation(vehicleLoc);
        		}
        		
        		// Person has a car
        		if(!((Person)spatial).hasVehicle()) {
        			veh.setCurrentlyUsed(true);
        			
        			// Hide the player
        			((Person)spatial).setCullHint(CullHint.Always);
        			
        			((Person)spatial).setVehicle(veh);
        		}
        	}else{
        		if(((Person)spatial).hasVehicle()) {
        			// Exit Car
        			((Person)spatial).getVehicle().setCurrentlyUsed(false);
        			
        			// Show the player again
        			((Person)spatial).setCullHint(CullHint.Never);
        			
        			//((Person)spatial).getVehicle().setLocalTranslation(
        			//		((Person)spatial).getVehicle().getLocalTranslation().clone());
        			((Person)spatial).setVehicle(null);
        		}
        		
        		p.setLocalTranslation(
            			new Vector3f(m.getPositionX(),
            			m.getPositionY(),
            			m.getPositionZ()));
            	
            	p.getBody().getLocalRotation().x = m.getRotationX();
            	p.getBody().getLocalRotation().y = m.getRotationY();
            	p.getBody().getLocalRotation().z = m.getRotationZ();
            	p.getBody().getLocalRotation().w = m.getRotationW();
            	
        	}
        	
        	if(!((Person)spatial).hasVehicle()) {
        		if(m.getAnimation() != SynchronizePlayerMessage.ANIMATION_SWIMMING &&
        				((Person)spatial).getAnimation().isSwimming()) {
        			// Rotate back
        			((Person)spatial).getAnimation().stopSwimming();
        		}
        		
        		
        		if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_FALLDEAD) {
            		((Person)spatial).getAnimation().fall();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_SWIMMING) {
            		if(!((Person)spatial).getAnimation().isSwimming()) {
            			((Person)spatial).getAnimation().swimming();
            		}
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_FIRING) {
            		((Person)spatial).getAnimation().fireAnimation();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_STAND) {
            		((Person)spatial).getAnimation().stand();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_RUN) {
            		((Person)spatial).getAnimation().walk();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_JUMP) {
            		((Person)spatial).getAnimation().jump();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_WALK) {
            		((Person)spatial).getAnimation().sneakWalking();
            	}else if(m.getAnimation() == SynchronizePlayerMessage.ANIMATION_DUCK) {
            		((Person)spatial).getAnimation().duck();
            	}
        		
        	}
        	
        	
        }
    }

    public SynchronizeMessage createSynchronizationMessage(Spatial spatial) {
    	SynchronizePlayerMessage message = new SynchronizePlayerMessage();
        message.setPositionX(spatial.getLocalTranslation().x);
        message.setPositionY(spatial.getLocalTranslation().y);
        message.setPositionZ(spatial.getLocalTranslation().z);
        message.setRotationX(spatial.getLocalRotation().x);
        message.setRotationY(spatial.getLocalRotation().y);
        message.setRotationZ(spatial.getLocalRotation().z);
        message.setRotationW(spatial.getLocalRotation().w);
        
        // set animation
        if(spatial instanceof Person) {
        	Person p = (Person) spatial;
        	
        	if(!((Person)spatial).hasVehicle()) {
        		message.setPositionX(p.getLocalTranslation().x);
        		message.setPositionY(p.getLocalTranslation().y);
        		message.setPositionZ(p.getLocalTranslation().z);
        	}
        	
        	if(((Person)spatial).isDead()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_FALLDEAD);
        	}else if(((Person)spatial).getAnimation().isSwimming()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_SWIMMING);
        	}else if(((Person)spatial).getAnimation().isFiring()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_FIRING);
        	}else if(((Person)spatial).getAnimation().isWalking()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_RUN);
        	}else if(((Person)spatial).getAnimation().isJumping()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_JUMP);
        	}else if(((Person)spatial).getAnimation().isSneakWalking()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_WALK);
        	}else if(((Person)spatial).getAnimation().isDucking()) {
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_DUCK);
        	}else{
        		message.setAnimation(SynchronizePlayerMessage.ANIMATION_STAND);
        	}
        	message.setBulletColor(((Person)spatial).getBulletColor());
        	message.setPlayerName(((Person)spatial).getPlayerName());
        	message.setScore(((Person)spatial).getScore());
        	
        	message.setTeam(((Person)spatial).getTeam());
        	
        	if(((Person)spatial).hasVehicle()) {
        		Vehicle veh = ((Person)spatial).getVehicle();
    			message.setVehicleIndex(((Person)spatial).getVehicle().getVehicleIndex());
        		if(veh instanceof Car) {
        			message.setRotationX(((Car)veh).getPhysicsCar().getLocalRotation().x);
        	        message.setRotationY(((Car)veh).getPhysicsCar().getLocalRotation().y);
        	        message.setRotationZ(((Car)veh).getPhysicsCar().getLocalRotation().z);
        	        message.setRotationW(((Car)veh).getPhysicsCar().getLocalRotation().w);
        	        
        	        message.setPositionX(((Car)veh).getPhysicsCar().getLocalTranslation().x);
	                message.setPositionY(((Car)veh).getPhysicsCar().getLocalTranslation().y);
	                message.setPositionZ(((Car)veh).getPhysicsCar().getLocalTranslation().z);
        		}else{
            		message.setRotationX(((Person)spatial).getVehicle().getLocalRotation().x);
        	        message.setRotationY(((Person)spatial).getVehicle().getLocalRotation().y);
        	        message.setRotationZ(((Person)spatial).getVehicle().getLocalRotation().z);
        	        message.setRotationW(((Person)spatial).getVehicle().getLocalRotation().w);
        	        
        		}
        	}
        }
        
        return message;
    }

    /**
     * This method will always return 1.0f. It is recommended to override this method
     * in games to provide better efficiency to synchronization.
     */
    public float proximity(Spatial spatial, short playerId) {
        return 1f;
    }

    /**
     * This method will always return true. It is recommended to override this method
     * in games to provide a layer of security.
     */
    public boolean validateMessage(SynchronizeMessage message, Spatial spatial) {
        return true;
    }

	public boolean validateCreate(SynchronizeCreateMessage message) {
		return true;
	}

	public boolean validateRemove(SynchronizeRemoveMessage message) {
		return true;
	}
}
